/**
 * Jaxson ajax
 *
 * Copyright Remedy Interactive, licensed under Apache version 2 license:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0.html
 *
 * This notice must remain in all java source files.
 */
package org.jaxson.struts.json;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Joe Maisel
 *
 */
public class JsonParameterAnnotations {
	
	private static final Log lager = LogFactory.getLog(JsonParameterAnnotations.class);
	private static final Map<Class<?>, List<JsonParameterDescriptor>> jsonParameters = new HashMap<Class<?>, List<JsonParameterDescriptor>>();
	
	public static class JsonParameterDescriptor
	{
		protected JsonParameterDescriptor(JsonParameter param, Class<?> type, Method setter )
		{
			this.parameter = param;
			this.type = type;
			this.setter = setter;
		}
		
		public JsonParameter parameter;
		public Class<?> type;
		public Method setter;
	}
	
	
	private static void add(Class<?> cls, JsonParameter a, Class<?> type, Method m ) {
		if( !jsonParameters.containsKey(cls) )
			jsonParameters.put(cls, new ArrayList<JsonParameterDescriptor>());
		
		jsonParameters.get(cls).add(new JsonParameterDescriptor(a, type, m));
	}
	
	@SuppressWarnings("unchecked")
	public static List<JsonParameterDescriptor> get( Class<?> cls ){
		return jsonParameters.get(cls) == null?new ArrayList():jsonParameters.get(cls);
	}
	
	public static void parse( Class<?> cls ) throws SecurityException, NoSuchMethodException{
		
		if( jsonParameters.containsKey(cls) )
			return;
		
		lager.debug( "parsing " + cls );
		
		for( Field f : cls.getDeclaredFields() )
		{
			JsonParameter ann = f.getAnnotation(JsonParameter.class);
			
			if( ann == null )
				continue;
			
			String methodName = "set" + f.getName().toUpperCase().charAt(0) + f.getName().substring(1);
			add( cls, ann, f.getType(), cls.getDeclaredMethod( methodName, f.getType() ) );
		}
	}
}
